#include "StdAfx.h"
#include "Tablet.h"


IMPLEMENT_DYNAMIC(CTablet, CWnd)

CTablet::~CTablet()
{
	m_pIter = m_pSData.begin();
	while(m_pIter != m_pSData.end())
	{
		delete *m_pIter;
		m_pIter++;
	}
	if(m_pBitmap)
	{
		m_pBitmap->DeleteObject();
		delete m_pBitmap;
	}

	if(m_MemDC)
	{
		delete m_MemDC;
	}
	
}

void CTablet::InitFrame()
{
	//accroding to the current client rect size
	//to calculate the proper per-row-item-count
	if(!m_itemCount)
		return;
	CRect rect;
	GetClientRect( &rect );
	m_pActualHeight = rect.Height();
	m_pWinHeight = m_pActualHeight;
	CalcRandM();
	RedrawItems(false);
}

void CTablet::DrawRectangle(CDC* pDC,const CRect& rect,COLORREF clr,int nPensize /* =1 */)
{
	if(pDC)
	{
		CPen pen( PS_SOLID, nPensize, clr );
		CPen* pOldPen = pDC->SelectObject( &pen );
		pDC->MoveTo( rect.TopLeft( ) );
		pDC->LineTo( rect.right, rect.top );
		pDC->LineTo( rect.right, rect.bottom );
		pDC->LineTo( rect.left, rect.bottom );
		pDC->LineTo( rect.left, rect.top );
		pDC->SelectObject( pOldPen );
	}
}


void CTablet::DrawszName(CDC* pDC,const CRect& rect,COLORREF clr,int nPenSize,TCHAR* szName)
{
	if( pDC )
	{
		CRect Trect;
		Trect.CopyRect( &rect );
		pDC->SetBkMode( TRANSPARENT );
		CFont* pFont = CFont::FromHandle( (HFONT)::GetStockObject( DEFAULT_GUI_FONT ) );
		pDC->SelectObject( pFont );
		pDC->SetTextColor( clr );
		pDC->DrawText(szName,Trect,DT_SINGLELINE | DT_CENTER |DT_VCENTER );
		
		/*int32 nLen = _tcslen( szName );
		if( nLen < Trect.Width() )
			pDC->DrawText(szName,Trect,DT_SINGLELINE | DT_VCENTER );
		else
		{
			TCHAR* szNewName = new TCHAR[ Trect.Width() * sizeof(TCHAR) ];
			memset( szNewName, _T("."), Trect.Width() * sizeof(TCHAR) );
			_tcsncpy( szNewName, szName, (Trect.Width() - 3)*sizeof(TCHAR) );
		}*/
	}
}

BOOL CTablet::Create(const RECT& rect, CWnd* pParentWnd, UINT nID, DWORD dwstyle/* =WS_CHILD|WS_VISIBLE */)
{
	if(!CWnd::Create(NULL,_T("tablet"),dwstyle,rect, pParentWnd, nID))
		return FALSE;

	return TRUE;
}

void CTablet::ExtendBitmap(/*int nwidth,*/ int ngrow)
{
	m_pActualHeight += ngrow;
	CRect rect;
	GetClientRect( &rect );
	if(m_pBitmap) {
		m_pBitmap->DeleteObject();
		delete m_pBitmap;
		m_pBitmap = NULL;
		m_pBitmap = new CBitmap();
		m_pBitmap->CreateCompatibleBitmap( m_MemDC, rect.Width(), m_pActualHeight );
		CBitmap* pOld = m_MemDC->SelectObject(m_pBitmap);
		rect.bottom = m_pActualHeight + rect.top;
		m_MemDC->FillSolidRect(&rect, RGB(255,255,255));
	}
	
	//RedrawItems();


}

void CTablet::SetVscrollInfo(int cur, int act)
{
	int range = act - cur;
	if(range > 0)
	{
		SCROLLINFO info;
		info.cbSize = sizeof(SCROLLINFO);
		info.fMask = SIF_ALL;
		info.nMax = act;//change 1
		info.nMin = 0;
		info.nPage = cur;
		info.nPos = min(0,act - cur - 1);
		SetScrollInfo(SB_VERT,&info,TRUE);
		SetWindowLong(GetSafeHwnd(), GWL_STYLE, GetWindowLong(GetSafeHwnd(), GWL_STYLE) | WS_VSCROLL);
		ShowScrollBar(SB_VERT,TRUE);
		m_bScroll = TRUE; //for skin's scrollbar only
	}
	else
	{
		SCROLLINFO info;
		info.cbSize = sizeof(SCROLLINFO);
		info.fMask = SIF_RANGE;
		info.nMax = 0;
		info.nMin = 0;
		SetScrollInfo(SB_VERT,&info,TRUE);
		SetWindowLong(GetSafeHwnd(), GWL_STYLE, GetWindowLong(GetSafeHwnd(), GWL_STYLE) ^ WS_VSCROLL);
		ShowScrollBar(SB_VERT,FALSE);
		m_bScroll = FALSE; //for skin's scrollbar only
	}
}

void CTablet::MptInRect(CPoint curP)
{
	//check if there is scroll bar
	int pos=0;
	if( m_bScroll )
	{
		SCROLLINFO info={0};
		info.cbSize = sizeof(SCROLLINFO);
		GetScrollInfo( SB_VERT, &info ,SIF_POS);
		pos = 0 - info.nPos;
	}

	int ncurow = (curP.y - pos) / OUT_FRAME_HEIGHT;
	ncurow++;
	
	int npos = curP.x / OUT_FRAME_WIDTH;
	++npos;
	m_pIter = m_pSData.begin();
	size_t nnpos = (ncurow-1)*m_pRowItemCount + npos;
	if(nnpos <= m_pSData.size() )
	{
		TRACE(_T("cur row: %d\n"), ncurow );
		TRACE(_T("item count: %d\n") ,nnpos);
	}
	return ;
	

}

void CTablet::UpdateScrollbar(int nbot)
{
	SCROLLINFO info = {0};
	info.cbSize = sizeof(info);
	GetScrollInfo(SB_VERT,&info,SIF_ALL);
	int ncur = info.nMax;
	if(nbot <= ncur)
		return;
	info.nMax = nbot;
	info.nMin =0;
	//info.nPage = ncur;
	//info.nPos = min(0,nbot-info.nPage-1);
	SetScrollInfo(SB_VERT,&info,TRUE);
}

void CTablet::AddOneItem(TCHAR *szExname, ...)
{
	CRect irect;
	irect.CopyRect( &m_lastRect );
	if( m_itemCount % m_pRowItemCount || !m_itemCount )
	{
		if(m_itemCount)
			irect.OffsetRect( DEFAUTL_MARGIN + OUT_FRAME_WIDTH, 0);
	}
	else
	{	
		irect.CopyRect( &m_initRect );
		irect.OffsetRect( 0, (OUT_FRAME_HEIGHT + DEFAUTL_MARGIN) * (m_itemCount / m_pRowItemCount) );
		++m_pRow;
		TRACE( _T("%d\n"), m_pRow );
	}

	UpdateCount(TRUE);
	m_lastRect.CopyRect( &irect );

	if(irect.bottom > m_pActualHeight )
	{
		SetVscrollInfo(m_pWinHeight, irect.bottom);
		CalcRandM();
		ExtendBitmap( irect.bottom - m_pActualHeight + DEFAULT_EXTEND_MOUNT*OUT_FRAME_HEIGHT);
		RedrawItems();
	}else{

		m_bAdded = false;
		DrawItem( irect, szExname );
		if(m_bScroll)
		{
			//update scroll bar
			UpdateScrollbar( irect.bottom );

		}
	}

	TRACE(_T("total count: %d\n"), m_pSData.size() );

	Invalidate(  );

	return ;
}

void CTablet::DeleteOneItem( DWORD pData )
{
	m_pIter = m_pSData.begin();
	while(m_pIter != m_pSData.end() )
	{
		if( pData == (*m_pIter)->m_pData )
		{
			m_pSData.erase( m_pIter);
			UpdateCount();

			//////////////////////////////////////////////////////////////////////////
			//
			CRect rect;
			rect.CopyRect( &m_lastRect );
			rect.bottom += 1;
			rect.right += 1;
			m_MemDC->FillSolidRect( &rect, RGB(255,255,255));


			//////////////////////////////////////////////////////////////////////////
			RedrawItems();
			Invalidate( );
			break;
		}
	}

	TRACE(_T("cur count: %d\n"), m_itemCount );
	TRACE(_T("l:%d, t:%d, r:%d, b:%d\n"), m_lastRect.left, m_lastRect.top, m_lastRect.right, m_lastRect.bottom );

}

void CTablet::DrawItem(CRect& irect,TCHAR* szName)
{
	CDC* dc = GetDC();
	CRect rect;
	GetClientRect(&rect);

	if(m_MemDC==NULL)
	{
		m_MemDC = new CDC();
		m_MemDC->CreateCompatibleDC(dc);
	}

	if(m_pBitmap==NULL)
	{
		m_pBitmap = new CBitmap();
		m_pBitmap->CreateCompatibleBitmap( dc, rect.Width(), m_pActualHeight);
		CBitmap* pOld = m_MemDC->SelectObject(m_pBitmap);
		m_MemDC->FillSolidRect(&rect, RGB(255,255,255));
	}

	//////////////////////////////////////////////////////////////////////////
	/////////////// to be fixed                            ///////////////////
	///////////////                                        ///////////////////
	///////////////                                        ///////////////////
	///////////////                                        ///////////////////
	///////////////                                        ///////////////////
	//////////////////////////////////////////////////////////////////////////
	
#ifdef ITEM_INFO
	/*if(!m_bAdded)
	{	
		CItemInfoEx* pinfo = new CItemInfoEx();
		pinfo->m_pData = 0;
		m_pSData.push_back(pinfo);
	}*/
#endif
	

	CRect mrect;
	mrect.CopyRect( &irect );

	//draw out frame
	DrawRectangle(m_MemDC, mrect, RGB(0,0,0), 1);

	//draw inner frame
	CPoint ip(mrect.left+DEFAUTL_MARGIN,mrect.top+DEFAUTL_MARGIN);
	CRect inrect(ip,m_InnerBound);

	DrawRectangle(m_MemDC,inrect, RGB(255,0,0),1);

	//draw name
	//calculate area
	CPoint ipp(inrect.left,inrect.bottom);
	CSize isz(inrect.Width(),NAME_FRAME_HEIGHT);
	CRect nrect(ipp,isz);

	DrawszName(m_MemDC, nrect, RGB(0,0,0), 1, szName);
}






BEGIN_MESSAGE_MAP(CTablet, CWnd)
	ON_WM_ERASEBKGND()
	ON_WM_PAINT()
	ON_WM_VSCROLL()
	ON_WM_LBUTTONDOWN()
	ON_WM_RBUTTONDOWN()
END_MESSAGE_MAP()

BOOL CTablet::OnEraseBkgnd(CDC* pDC)
{
	// TODO: ?????????????/??????

	return TRUE;
}

void CTablet::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: ?????????????
	// ???????? CWnd::OnPaint()
	UptoWindow( &dc );
}

void CTablet::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: ?????????????/??????
	SCROLLINFO info = {0};
	info.cbSize = sizeof(info);
	GetScrollInfo(SB_VERT,&info,SIF_ALL);

	int lastPos = info.nPos;
	switch(nSBCode)
	{
	case SB_LINEUP:
		info.nPos -= 1;
		break;
	case SB_LINEDOWN:
		info.nPos += 1;
		break;
	case SB_THUMBTRACK:
		info.nPos = info.nTrackPos;
		break;
	case SB_PAGEDOWN:
		info.nPos += info.nPage;
		break;
	case SB_PAGEUP:
		info.nPos -= info.nPage;
		break;
	default:
		return;
	}

	int maxPos = m_pActualHeight - m_pWinHeight;
	if(info.nPos < 0)
		info.nPos = 0;
	else if(info.nPos > maxPos)
		info.nPos = maxPos;
	info.fMask = SIF_POS;
	info.nMax = maxPos;
	info.nMin = 0;

	SetScrollInfo(SB_VERT,&info,TRUE);
	GetScrollInfo(SB_VERT,&info,TRUE);
	if(lastPos != info.nPos)
	{
		ScrollWindow(0,lastPos - info.nPos);
		Invalidate();
		//UpdateWindow();
	}

}

void CTablet::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: ?????????????/??????
	
	MptInRect(point);

	CWnd::OnLButtonDown(nFlags, point);
}

void CTablet::OnRButtonDown(UINT nFlags, CPoint point)
{
	// TODO: ?????????????/??????

	DeleteOneItem( 0 ); 

	CWnd::OnRButtonDown(nFlags, point);
}
